#!/bin/bash
SCRIPT_PATH=$(cd "$(dirname "$0")" || exit; pwd)
SCRIPT_NAME=$(basename $0)
BACKUP_PATH=${SCRIPT_PATH}/.backup
DEPLOY_PATH=${SCRIPT_PATH}/.deploy
SCRIPT_LOG="${SCRIPT_PATH}/${SCRIPT_NAME%.*}.log"
TMP_LOG="${SCRIPT_PATH}/.${SCRIPT_NAME%.*}.log"
KUBECONFIG="${SCRIPT_PATH}/kubeconfig"
## 加载配置文件
. "${SCRIPT_PATH}"/install.conf


## echo_log
function echo_log(){
    echo -e "$*" | tee -a ${SCRIPT_LOG}
}


## 判断状态码输出日志，异常不退出
function echo_cs(){
    if [[ "$?" -eq 0 ]];then
        echo_log "\e[1;32m$(date +'%F %T') [INFO] - $* Success! \e[0m"
    else
        echo_log "\e[1;31m$(date +'%F %T') [FAIL] - $* Fail! \e[0m"
    fi
}

## 判断状态码输出日志，异常不退出
function echo_cs_exit(){
    if [[ "$?" -eq 0 ]];then
        echo_log "\e[1;32m$(date +'%F %T') [INFO] - $* Success! \e[0m"
    else
        echo_log "\e[1;31m$(date +'%F %T') [FAIL] - $* Fail! \e[0m"
        exit 1
    fi
}


## 创建备份目录和部署目录
mkdir -p "${BACKUP_PATH}"
mkdir -p "${DEPLOY_PATH}"
if [ -f "${SCRIPT_LOG}" ];then
    > ${SCRIPT_LOG}
else
    touch ${SCRIPT_LOG}
fi

## 运行前置检查
function pre_check(){
    kubectl --kubeconfig=${KUBECONFIG} cluster-info >> /dev/null 2>&1
    echo_cs_exit "Check: kubernetes cluster-info"
    helm version | grep v3 >> /dev/null 2>&1
    echo_cs_exit "Check: helm version"
    test -n "${NAMESPACE}" >> /dev/null 2>&1
    echo_cs_exit "Check: NAMESPACE var configure"
    kubectl --kubeconfig=${KUBECONFIG} get ns "${NAMESPACE}" >> /dev/null 2>&1
    echo_cs_exit "Check: kubernetes namespace. \"kubectl create ns ${NAMESPACE}\""
    if [[ "${PV_ENABLED}" =~ [T/t][R/r][U/u][E/e] ]];then
        kubectl --kubeconfig=${KUBECONFIG}  get pvc "${PVC_NAME}" -n "${NAMESPACE}" >> /dev/null 2>&1
        echo_cs_exit "Check: kubernetes pvc. execute install.sh input 4 create pvc."
    fi
}


## 检查目录或文件是否存在
function check_dir_file(){
    if [ ! -d "$1" ] && [ ! -f "$1" ] ;then
        echo_cs "Directory or file $1 does not exist, please check!"
        exit 1
    fi
}


## 获取需要部署的product list
function get_product_list(){
    local product_conf=${SCRIPT_PATH}/product-list.conf
    check_dir_file "$product_conf"
    PRODUCT_LIST=""
    while read -r product || [[ -n ${product} ]]
    do
        if [[ ! $product =~ ^#.*$ ]] && [[ ! $product =~ ^$ ]] ;then
            PRODUCT_LIST="${PRODUCT_LIST} ${product}"
        fi
    done < "${product_conf}"
}


## 备份拷贝对应product至DEPLOY_PATH
function init_helm_file(){
    cd "${SCRIPT_PATH}" || exit
    cp -rf "${DEPLOY_PATH}" ${BACKUP_PATH}/deploy_bak_$(date +'%Y%m%d%H%M')
    rm -rf "${DEPLOY_PATH}"/*
    for product in ${PRODUCT_LIST}
    do
        echo "$product"
        check_dir_file "../${product}"
        /bin/cp -rf ../${product} "${DEPLOY_PATH}"
        rm -rf "${DEPLOY_PATH}"/"${product}"/.git
    done
}


## 替换变量函数 - Substituting variables
function modify_file_func(){
    local KEY=$1
    local VALUE=$2
    if [ "$(uname)" == "Darwin" ]
    then
        echo "sed -i '' -e \"s#${KEY}#${VALUE}#g\""
        sed -i '' -e "s#${KEY}#${VALUE}#g" $(grep -rl "${KEY}" * | grep -e  "values.*.yaml" -e "configmap.*.yaml") > /dev/null 2>&1
    else
        sed -i  "s#${KEY}#${VALUE}#g" $(grep -rl ${KEY} ./*|grep  -e  "values.*.yaml" -e "configmap.*.yaml") > /dev/null 2>&1
        echo_cs "sed ${KEY} to ${VALUE}"
    fi
}


## 根据配置文件使用modify_file_func替换变量
function modify_conf_file(){
    local FILE_PATH=$1
    while read -r line || [[ -n ${line} ]]
    do
        if [[ ! $line =~ ^#.*$ ]] && [[ ! $line =~ ^$ ]] ;then
            modify_key=$(echo "${line}" |cut -d '=' -f 1)
            #echo "${modify_key}"
            modify_file_func "@{${modify_key}}" "$(eval echo \$"$modify_key")"
        fi
    done < "${FILE_PATH}"

}


## 执行替换变量
function modify_yaml(){
    init_helm_file
    cd "${DEPLOY_PATH}" || exit
    modify_conf_file "${SCRIPT_PATH}/install.conf"
}


## 部署函数
function deploy_product(){
    local model=$1
    for product in ${PRODUCT_LIST}
    do
        if [[ "${model}" == "upgrade" ]] && [[ ${product} == "fano-common-ucharts" ]];then
            continue
        elif [[ "${model}" == "upgrade" ]] || [[ "${model}" == "install" ]]; then
            helm_release_name=${product%-ucharts*}
            echo "helm upgrade --install -f values-tag.yaml ${helm_release_name} . -n ${NAMESPACE}" > "${DEPLOY_PATH}"/"${product}"/deploy.sh
            helm --kubeconfig=${KUBECONFIG}  upgrade --install -f "${DEPLOY_PATH}"/"${product}"/values-tag.yaml "${helm_release_name}" "${DEPLOY_PATH}"/"${product}" -n "${NAMESPACE}"
            echo_cs_exit "helm upgrade --install -f .deploy/${product}/values-tag.yaml ${helm_release_name} .deploy/${product} -n ${NAMESPACE}" >> ${TMP_LOG} 2>&1
        else
            exit 1
        fi
    done
    cat "${TMP_LOG}" && rm -f "${TMP_LOG}"
}


## 检查pod status
function check_service_status()
{
    local service_name=$1
    local namespace=$2
    result_status=False
    for pod_name in $(kubectl --kubeconfig=${KUBECONFIG} get po -n "${namespace}"  --sort-by=.status.startTime |grep "${service_name}"|awk '{print $1}' )
    do
        result_value=$(kubectl --kubeconfig=${KUBECONFIG} get po -n "${namespace}"  "${pod_name}" -o jsonpath="{.status.conditions[*].status}")
        if echo "$result_value"|grep  False >/dev/null 2>&1
        then
           result_status=False
           break
        else
           result_status=True
        fi
    done
    echo   ${result_status}
}


## 执行migrate db函数
function migrate_db(){
    local service_name=$1
    local program_type=$2
    if kubectl --kubeconfig=${KUBECONFIG} get deploy -n ${NAMESPACE} ${service_name} >> /dev/null 2>&1 ; then
        for count in {1..100}
        do
            status=$(check_service_status "$service_name" "$NAMESPACE")
            echo "$service_name $status"
            if [[ "${status}" == "False" ]]
            then
                echo "$service_name is not ready,please waiting...."
                if [ $count -eq 100 ]
                then
                    echo "$service_name  could not start,Please check manually.... " && exit 1
                fi
                sleep 10
            else
                pod_name=$(kubectl --kubeconfig=${KUBECONFIG} get po -n "${NAMESPACE}" |grep -E "${service_name}-(.){8,10}-(.){5}" |head -n 1|awk '{print $1}')
                if [[ "${program_type}" == "NODEJS" ]]
                then
                    if [ "$(echo "${service_name}"|grep "callinter")" != "" ];then
                        echo "kubectl exec ${pod_name} -n ${NAMESPACE} -- ${service_name} migrate:latest"
                        kubectl --kubeconfig=${KUBECONFIG} exec "${pod_name}" -n "${NAMESPACE}" -- ${service_name} migrate:latest
                        echo_cs "kubectl exec ${pod_name} -n ${NAMESPACE} -- ${service_name} migrate:latest"
                    else
                        echo "kubectl exec ${pod_name} -n ${NAMESPACE} -- yarn run migrate:latest"
                        kubectl --kubeconfig=${KUBECONFIG} exec "${pod_name}" -n "${NAMESPACE}" -- yarn run migrate:latest
                        echo_cs "kubectl exec ${pod_name} -n ${NAMESPACE} -- yarn run migrate:latest"
                    fi
                elif [[ "${program_type}" == "PYTHON" ]]
                then
                    echo "kubectl exec ${pod_name} -n ${NAMESPACE} -- python -u ./db_change/db_change_main.py"
                    kubectl --kubeconfig=${KUBECONFIG} exec "${pod_name}" -n "${NAMESPACE}" -- python -u ./db_change/db_change_main.py
                    echo_cs "kubectl exec ${pod_name} -n ${NAMESPACE} -- python -u ./db_change/db_change_main.py"
                fi
                sleep 1
                break
            fi
        done
    fi 
}


## upgrede callinter相关db
function upgrade_callinter_db(){
    migrate_db "fano-ms-callinter-analyze-worker" "NODEJS"
    migrate_db "fano-ms-callinter-crud" "NODEJS"
    migrate_db "fano-ms-callinter-speech-adapter" "NODEJS"
}


## upgrade portal相关db
function upgrade_portal_db(){
    migrate_db "fano-portal-ms-datapanel" "NODEJS"
    migrate_db "fano-portal-ms-intent" "NODEJS"
    migrate_db "fano-portal-ms-tts" "NODEJS"
    migrate_db "fano-portal-ms-voiceprint" "NODEJS"
    migrate_db "fano-portal-ms-cloud" "NODEJS"
}


## upgrade db函数
function upgrade_db(){
    upgrade_portal_db
    echo_cs "execute upgrade portal command"
    upgrade_callinter_db
    echo_cs "execute upgrade callinter command"
}


## 创建pv函数
function create_pv(){
    cd "${SCRIPT_PATH}" || exit 1
    check_dir_file pvc.yaml
    cp -rf pvc.yaml .pvc.yaml
    if [ "$(uname)" == "Darwin" ]
    then
        sed -i '' "s#@{PVC_NAME}#${PVC_NAME}#g" .pvc.yaml > /dev/null 2>&1 
        sed -i '' "s#@{PVC_SIZE}#${PVC_SIZE}#g" .pvc.yaml > /dev/null 2>&1
    elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]
    then
        sed -i  "s#@{PVC_NAME}#${PVC_NAME}#g" .pvc.yaml > /dev/null 2>&1 
        sed -i  "s#@{PVC_SIZE}#${PVC_SIZE}#g" .pvc.yaml > /dev/null 2>&1
    fi
    kubectl --kubeconfig=${KUBECONFIG} apply -f .pvc.yaml -n "${NAMESPACE}"
    echo_cs "kubectl apply -f .pvc.yaml -n ${NAMESPACE}"
}


## 选项列表
function display_help()
{
usage="$(basename "$0") [-h] [-m] [-i] [-u] [-p] [-d]
where:
    -h  display help
    -m  modify_yaml
    -i  install
    -u  upgrade
    -p  create pv
    -d  upgrade db
    "
  echo "$usage"
  exit 0
}


## 入口函数
function main(){
    if [[ ! -n $* ]];then
        display_help
    fi
    # pre_check
    get_product_list
    echo_cs "deploy list: ${PRODUCT_LIST}"
    while getopts ':miupd' option; do
        case "${option}" in
        h)
            display_help
            exit 0
        ;;
        i)
            modify_yaml
            deploy_product install
        ;;
        u)
            modify_yaml
            deploy_product upgrade
        ;;
        p)
            create_pv
        ;;
        d)
            echo_log "sleep 30s" && sleep 30 
            upgrade_db
        ;;
        ?)
            display_help
            exit 1
        ;;
        esac
    done
}

main $*
